<template>
  <div class="codeMirror-editor-container">
    <textarea ref="codeMirrorEditor" v-model="value"></textarea>
    <div class="language-container">
      <el-dropdown trigger="click">
        <el-button class="language-name" size="small">
          <span class="name">{{ mode }}</span>
        </el-button>
        <template #dropdown>
          <el-dropdown-menu class="language-dropitem">
            <template v-for="item in modes">
              <el-dropdown-item @click.native="switchLanguage(item)">
                {{ item.label }}
              </el-dropdown-item>
            </template>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>
  </div>
</template>

<script>
// 核心样式
import 'codemirror/lib/codemirror.css'
// 引入主题，需在options指定主题才能生效
import 'codemirror/theme/idea.css'
import 'codemirror/theme/blackboard.css'
// 引入代码自动提示插件
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/javascript-hint'
import 'codemirror/addon/hint/sql-hint'
// 括号匹配,自动补全括号
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/edit/closebrackets'
// 引入具体的语法高亮库，实现高亮效果
import 'codemirror/mode/javascript/javascript'
import 'codemirror/mode/markdown/markdown'
import 'codemirror/mode/sql/sql'
import 'codemirror/mode/php/php'
import 'codemirror/mode/python/python'
import 'codemirror/mode/shell/shell'
import 'codemirror/mode/powershell/powershell'

// 引入全局实例
import _CodeMirror from 'codemirror'
import { dataBaseData } from '@/mock/jsModule/dataBase.js'
export default {
  name: 'index',
  props:{
    value:{
      type: String,
      default: ''
    },
    language:{
      type: String,
      default: 'javascript'
    }
  },

  data() {
    return {
      CommonEditor: false,
      code: '',
      coder: null,
      mode: '',
      options: {},
      modes: [
        { value: 'javascript', label: 'javascript' },
        { value: 'x-java', label: 'java' },
        { value: 'x-python', label: 'python' },
        { value: 'x-sql', label: 'sql' },
        { value: 'x-php', label: 'php' },
        { value: 'x-markdown', label: 'markdown' }
      ],
      tables: {},
    }
  },
  watch:{
    value:{
      deep: true,
      immediate: true,
      handler(val){
        this.code = val
        // 编辑器内容被清空时重新设置值
        if(!val){
          this.setCodeContent('')
        }
      }
    },
    language:{
      deep: true,
      immediate: true,
      handler(val){
        this.mode = val
      }
    }
  },
  computed: {
    coderOptions () {
      const defaultOptions = {
        line: true,
        mode: `text/${this.mode}`,
        theme: 'idea', //设置主题 记得引入对应主题才有显示   import 'codemirror/theme/idea.css'
        // tabSize: 4,    // tab字符的大小，默认为4个空格
        lineNumbers: true, // 显示行号
        cursorHeight: 1, //光标高度，默认是1
        autoCloseBrackets: true,
        matchBrackets: true, // 括号匹配
        lineWrapping: 'wrap', // 文字过长时，是换行(wrap)还是滚动(scroll),默认是滚动
        showCursorWhenSelecting: true, // 文本选中时显示光标
        smartIndent: false, // 智能缩进，是否使用mode提供的上下文的缩进
        indentUnit: 4,     // 缩进大小，4个空格
        hintOptions:{
          completeSingle: false, // 当匹配只有一项的时候是否自动补全
          // codeMirror只能实现两级级联，即 库名.表名  表名.字段名
          tables: this.tables
        }
      }
      const obj = Object.assign({}, defaultOptions, this.options)
      return obj
    }
  },
  mounted () {
    this.initCodeEditor()
    this.definedDataBase()
  },
  methods:{
    initCodeEditor(){
      // 初始化编辑器实例，传入需要被实例化的文本域对象和默认配置
      this.coder = _CodeMirror.fromTextArea(
        this.$refs.codeMirrorEditor,
        this.coderOptions
      )
      // 输入时提示补全内容
      this.coder.on('inputRead', () => {
        this.coder.showHint()
      })
      // 编辑器赋值
      if (this.value || this.code) {
        this.setCodeContent(this.value || this.code)
      } else {
        this.coder.setValue('')
      }
      // 支持双向绑定
      this.coder.on('change', (coder) => {
        this.code = coder.getValue()
        this.$emit('codeChange', this.code)
      })
    },
    // 编辑器赋值
    setCodeContent(value){
      setTimeout(() =>{
        if(!value){
          this.coder.setValue('')
        }else{
          this.coder.setValue(value)
        }
      },300)
    },
    // 切换语言
    switchLanguage(item){
      this.mode = item.label
      this.$emit('codeChange', '')
      setTimeout(() =>{
        this.coder.setOption('mode',`text/${item.value}`)
      },300)
    },
    // sql语言，自定义数据库表字段自动补全规则
    // 自定义实现补全 库名.表名.字段名
    definedDataBase(){
      const dbData = JSON.parse(JSON.stringify(dataBaseData))
      const dbName = dbData.dataBaseName
      const tbName = dbData.tableName
      const props = dbData.properties
      const tables = {}
      dbName.forEach((dbItem, dbIndex) =>{
        tbName.forEach((tbItem, tbIndex) =>{
          let keys = ''
          if(tbItem.dbId == dbItem.dbId){
            keys = dbItem.dbName + '.' + tbItem.tbName
            tables[`${keys}`] = []
            props.forEach((v, index) =>{
              if(v.tbId == tbItem.tbId){
                tables[`${keys}`].push(v.propName)
              }
            })
          }
        })
      })
      this.tables = tables
      // 现有实例参数
      const hintOptions = this.coder.getOption('hintOptions')
      // 动态设置tables参数
      this.coder.setOption('hintOptions',{
        ...hintOptions,
        tables:{
          ...hintOptions.tables,
          ...tables
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.codeMirror-editor-container{
  position: relative;
}
.language-container{
  position: absolute;
  z-index: 100;
  bottom: 10px;
  right: 0;
}
</style>

<style lang="scss">
.codeMirror-editor-container{
  .CodeMirror{
    height: calc(100vh - 260px) !important;
    font-family: initial !important;
    letter-spacing: 1px !important;
    line-height: 22px !important;
  }
}
.language-dropitem{
  .el-dropdown-menu__item{
    line-height: 26px !important;
    font-size: 10px !important;
  }
}
.language-name{
  padding: 5px 10px !important;
  .name{
    font-size: 10px !important;
  }
}
</style>
